#!/bin/bash -e


#      STEP 1
PERFORM_STEP_1=false
# Binutils-2.22 - Pass 1
# GCC-4.7.2 - Pass 1
# Linux-3.6.2 API Headers
# Glibc-2.16.0
#      CHECK


#      STEP 2
PERFORM_STEP_2=false
# Binutils-2.22 - Pass 2
# GCC-4.7.2 - Pass 2
#      CHECK


#      STEP 3
PERFORM_STEP_3=true
# Tcl-8.5.12
# Expect-5.45
# DejaGNU-1.5
# Check-0.9.8
# Ncurses-5.9
# Bash-4.2
# Bzip2-1.0.6
# Coreutils-8.19
# Diffutils-3.2
# File-5.11
# Findutils-4.4.2
# Gawk-4.0.1
# Gettext-0.18.1.1
# Grep-2.14
# Gzip-1.5
# M4-1.4.16
# Make-3.82
# Patch-2.7.1
# Perl-5.16.1
# Sed-4.2.1
# Tar-1.26
# Texinfo-4.13a
# Xz-5.0.4

#      STEP 4
PERFORM_STEP_4=true
# Stripping



echo	"
Set up a good working environment by creating 
two new startup files for the bash shell."

cat > ~/.bash_profile << EOF
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF

echo	"
The set +h command turns off bash's hash function"
echo	"
Setting the user file-creation mask (umask) to 
022 ensures that newly created files 
and directories are only writable by 
their owner, but are readable and 
executable by anyone"
echo	"
The LC_ALL variable controls the localization of certain programs"
echo	"
The LFS_TGT variable sets a non-default,
but compatible machine description for use 
when building our cross compiler and linker 
and when cross compiling our temporary toolchain."
echo	"
By putting /tools/bin ahead of the standard PATH, 
all the programs installed in Chapter 5 are 
picked up by the shell immediately after 
their installation."
cat > ~/.bashrc << EOF
set +h
umask 022
LFS=$LFS
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/tools/bin:/bin:/usr/bin
MAKEFLAGS=$MAKEFLAGS
export LFS LC_ALL LFS_TGT PATH MAKEFLAGS
EOF

#source ~/.bash_profile
set +h
umask 022
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/tools/bin:/bin:/usr/bin
export LFS LC_ALL LFS_TGT PATH MAKEFLAGS


echo	""
echo	""
echo	"---------------------------------------------"
echo	""
echo	"  Chapter 5. Constructing a Temporary System "
echo	""
echo	"---------------------------------------------"
echo	""
echo	""






CRTPKG=
TAR_OPTS=
TAR_TYPE=
TAR_OUT=
TMP_DIR=
SRC_DIR=
CRTLOG=
function 	initDirEx	{
	# $1 is the index to be printed
	# $2 is the file name
	# $3 is the file extension
	# $4 is the output directory from tar
	# $5 is a temp dir to create (may be empty)
	
	CRTPKG=$2
	TAR_OPTS=
	TAR_TYPE=$3
	TAR_OUT=$4
	TMP_DIR=$5
	CRTLOG=$LFS/sources/$CRTPKG.log
	SRC_DIR=$LFS/sources/$TAR_OUT
	echo	"
		Target $CRTPKG initialised at $(date)
		
		
	" >> $CRTLOG
	
	if [ "$TAR_TYPE" == "bz2" ]; then
		TAR_OPTS="jxf"
	elif [ "$TAR_TYPE" == "gz" ]; then
		TAR_OPTS="-zxf"
	elif [ "$TAR_TYPE" == "xz" ]; then
		TAR_OPTS="-Jxf"
	else
		echo	"ERROR!!! Unknown tar type: $TAR_TYPE"
		exit -1
	fi
	
	echo	""
	echo	""
	echo	"---------------------------------------------"
	echo	"  $1 $2"
	echo	"---------------------------------------------"
	echo	""
	echo	"Extracting $LFS/sources/$CRTPKG.tar.$TAR_TYPE"
	cd $LFS/sources
	tar $TAR_OPTS $CRTPKG.tar.$TAR_TYPE >> $CRTLOG
	cd ./$TAR_OUT
	
	if [ ! -z "$TMP_DIR" ]; then
		TMP_DIR="$LFS/sources/$TMP_DIR"
		mkdir -v $TMP_DIR
		cd $TMP_DIR
	fi
	echo	"Sources were extracted."
	
}

function 	initDir	{
	# $1 is the index to be printed
	# $2 is the file name without extension
	# $3 is the file extension
	# $4 is a temp dir to create (may be empty)
	initDirEx $1 $2 $3 $2 $4
}

function 	rDir	{
	# $1 is the source dir
	# $2 is a temp dir
	rm -rfv $SRC_DIR >> $CRTLOG
	if [ ! -z "$TMP_DIR" ]; then
		rm -rfv $TMP_DIR >> $CRTLOG
	fi
}

function 	finishDir	{
	make >> $CRTLOG
	make install >> $CRTLOG
	# $1 is the source dir
	# $2 is a temp dir
	rm -rfv $SRC_DIR >> $CRTLOG
	if [ ! -z "$TMP_DIR" ]; then
		rm -rfv $TMP_DIR >> $CRTLOG
	fi
}

function	doItAll		{
	# $1 is the index to be printed
	# $2 is the file name
	# $3 is the file extension
	# $4 is a temp dir to create (may be empty)
	initDir $1 $2 $3 $4
	./configure --prefix=/tools
	finishDir
}





# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#            STEP   1
# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
if $PERFORM_STEP_1; then

# ===============================================================
initDir "5.4." "binutils-2.22" "bz2" "binutils-build"
pushd $SRC_DIR
patch -Np1 -i ../binutils-2.22-build_fix-1.patch >> $CRTLOG
popd
$SRC_DIR/configure     \
    --prefix=/tools            \
    --with-sysroot=$LFS        \
    --with-lib-path=/tools/lib \
    --target=$LFS_TGT          \
    --disable-nls              \
    --disable-werror >> $CRTLOG
make >> $CRTLOG
case $(uname -m) in
  x86_64) mkdir -v /tools/lib && ln -sv lib /tools/lib64 ;;
esac
make install >> $CRTLOG
rDir
# ===============================================================


# ===============================================================
initDir "5.5." "gcc-4.7.2" "bz2" "gcc-build"
pushd $SRC_DIR

# GCC now requires the GMP, MPFR and MPC packages
tar -Jxf ../mpfr-3.1.1.tar.xz >> $CRTLOG
mv -v mpfr-3.1.1 mpfr
tar -Jxf ../gmp-5.0.5.tar.xz >> $CRTLOG
mv -v gmp-5.0.5 gmp
tar -zxf ../mpc-1.0.1.tar.gz >> $CRTLOG
mv -v mpc-1.0.1 mpc

# The following command will change the location of 
# GCC's default dynamic linker to use the one installed 
# in /tools. It also removes /usr/include from GCC's 
# include search path
for file in \
 $(find gcc/config -name linux64.h -o -name linux.h -o -name sysv4.h)
do
  cp -uv $file{,.orig}
  sed -e 's@/lib\(64\)\?\(32\)\?/ld@/tools&@g' \
      -e 's@/usr@/tools@g' $file.orig > $file
  echo '
#undef STANDARD_STARTFILE_PREFIX_1
#undef STANDARD_STARTFILE_PREFIX_2
#define STANDARD_STARTFILE_PREFIX_1 "/tools/lib/"
#define STANDARD_STARTFILE_PREFIX_2 ""' >> $file
  touch $file.orig
done

# GCC doesn't detect stack protection correctly, which causes
# problems for the build of Glibc-2.16.0, so fix that
# by issuing the following command:
sed -i '/k prot/agcc_cv_libc_provides_ssp=yes' gcc/configure

popd

# Prepare GCC for compilation: 
$SRC_DIR/configure         \
    --target=$LFS_TGT          \
    --prefix=/tools            \
    --with-sysroot=$LFS        \
    --with-newlib              \
    --without-headers          \
    --with-local-prefix=/tools \
    --with-native-system-header-dir=/tools/include \
    --disable-nls              \
    --disable-shared           \
    --disable-multilib         \
    --disable-decimal-float    \
    --disable-threads          \
    --disable-libmudflap       \
    --disable-libssp           \
    --disable-libgomp          \
    --disable-libquadmath      \
    --enable-languages=c       \
    --with-mpfr-include=$SRC_DIR/mpfr/src \
    --with-mpfr-lib=$(pwd)/mpfr/src/.libs >> $CRTLOG
    
    
make >> $CRTLOG
make install >> $CRTLOG

#Using --disable-shared means that the libgcc_eh.a file 
#isn't created and installed. The Glibc package depends on 
#this library as it uses -lgcc_eh within its build system. 
#This dependency can be satisfied by creating a symlink to
#libgcc.a, since that file will end up containing the objects 
#normally contained in libgcc_eh.a: 
ln -sv libgcc.a `$LFS_TGT-gcc -print-libgcc-file-name | sed 's/libgcc/&_eh/'`

rDir
# ===============================================================


# ===============================================================
# Linux headers
initDir "5.6." "linux-3.6.2" "xz"
	# Make sure there are no stale files and dependencies 
	# lying around from previous activity:
	make mrproper >> $CRTLOG

	# Now test and extract the user-visible kernel 
	# headers from the source. 
	# They are placed in an intermediate 
	# local directory and copied to the needed 
	# location because the extraction process removes 
	# any existing files in the target directory.

	make headers_check >> $CRTLOG
	make INSTALL_HDR_PATH=dest headers_install >> $CRTLOG
	cp -rv dest/include/* /tools/include
rDir
# ===============================================================



# ===============================================================
# Glibc-2.16.0 
initDir "5.7." "glibc-2.16.0" "xz" "glibc-build"
	pushd	$LFS/sources/glibc-2.16.0
		if [ ! -r /usr/include/rpc/types.h ]; then 
		  sudo -c 'mkdir -p /usr/include/rpc'
		  sudo -c 'cp -v sunrpc/rpc/*.h /usr/include/rpc'
		fi

		#  Fix an issue when building Glibc-2.16.0 with GCC-4.7.2: 
		sed -i 's/ -lgcc_s//' Makeconfig
	popd

	# Next, prepare Glibc for compilation:

	../glibc-2.16.0/configure                             \
		  --prefix=/tools                                 \
		  --host=$LFS_TGT                                 \
		  --build=$(../glibc-2.16.0/scripts/config.guess) \
		  --disable-profile                               \
		  --enable-add-ons                                \
		  --enable-kernel=2.6.25                          \
		  --with-headers=/tools/include                   \
		  libc_cv_forced_unwind=yes                       \
		  libc_cv_ctors_header=yes                        \
		  libc_cv_c_cleanup=yes  >> $CRTLOG
finishDir
# ===============================================================







# ===============================================================
# CHECKPOINT

cd $LFS/sources

echo	"


At this point, it is imperative to stop and ensure that the 
basic functions (compiling and linking) of the new 
toolchain are working as expected.

"
echo 'main(){}' > dummy.c
$LFS_TGT-gcc dummy.c
readelf -l a.out | grep ': /tools'

echo	"
If everything is working correctly, there should be no errors, 
and the output of the last command will be of the form:
[Requesting program interpreter: /tools/lib/ld-linux.so.2]
Note that /tools/lib, or /tools/lib64 for 64-bit machines appears 
as the prefix of the dynamic linker.

If the output is not shown as above or there was no output at all, 
then something is wrong. Investigate and retrace the steps to
find out where the problem is and correct it. This issue must 
be resolved before continuing on.

Press CTRL+C to stop.
Press RETURN to continue.
"

# Once all is well, clean up the test files:
rm -v "dummy.c" "a.out"

read dummy

# CHECKPOINT
# ===============================================================


fi




# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#            STEP   2
# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
if $PERFORM_STEP_2; then


# ===============================================================
initDir "5.8." "binutils-2.22" "bz2" "binutils-build"
pushd $SRC_DIR
	patch -Np1 -i ../binutils-2.22-build_fix-1.patch
popd

echo	"


===============================
SECOND PASS
===============================


" >> $CRTLOG

CC=$LFS_TGT-gcc            \
AR=$LFS_TGT-ar             \
RANLIB=$LFS_TGT-ranlib     \
$SRC_DIR/configure \
    --prefix=/tools        \
    --disable-nls          \
    --with-lib-path=/tools/lib >> $CRTLOG
    
make >> $CRTLOG
make install >> $CRTLOG

#  Now prepare the linker for the “Re-adjusting” phase in the next chapter: 
make -C ld clean >> $CRTLOG
make -C ld LIB_PATH=/usr/lib:/lib >> $CRTLOG
cp -v ld/ld-new /tools/bin

rDir
# ===============================================================


# ===============================================================
initDir "5.9." "gcc-4.7.2" "bz2" "gcc-build"
pushd $SRC_DIR

echo	"


===============================
SECOND PASS
===============================


" >> $CRTLOG

# GCC now requires the GMP, MPFR and MPC packages
tar -Jxf ../mpfr-3.1.1.tar.xz
mv -v mpfr-3.1.1 mpfr
tar -Jxf ../gmp-5.0.5.tar.xz
mv -v gmp-5.0.5 gmp
tar -zxf ../mpc-1.0.1.tar.gz
mv -v mpc-1.0.1 mpc

# Create a full version of the internal header using a command that is 
# identical to what the GCC build system does in normal circumstances:
cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \
  `dirname $($LFS_TGT-gcc -print-libgcc-file-name)`/include-fixed/limits.h


cp -v gcc/Makefile.in{,.tmp}
sed 's/^T_CFLAGS =$/& -fomit-frame-pointer/' gcc/Makefile.in.tmp \
  > gcc/Makefile.in
  
  
# The following command will change the location of 
# GCC's default dynamic linker to use the one installed 
# in /tools. It also removes /usr/include from GCC's 
# include search path
for file in \
 $(find gcc/config -name linux64.h -o -name linux.h -o -name sysv4.h)
do
  cp -uv $file{,.orig}
  sed -e 's@/lib\(64\)\?\(32\)\?/ld@/tools&@g' \
      -e 's@/usr@/tools@g' $file.orig >> $file
  echo '
#undef STANDARD_STARTFILE_PREFIX_1
#undef STANDARD_STARTFILE_PREFIX_2
#define STANDARD_STARTFILE_PREFIX_1 "/tools/lib/"
#define STANDARD_STARTFILE_PREFIX_2 ""' >> $file
  touch $file.orig
done

popd

CC=$LFS_TGT-gcc \
AR=$LFS_TGT-ar                  \
RANLIB=$LFS_TGT-ranlib          \
$SRC_DIR/configure          \
    --prefix=/tools             \
    --with-local-prefix=/tools  \
    --with-native-system-header-dir=/tools/include \
    --enable-clocale=gnu        \
    --enable-shared             \
    --enable-threads=posix      \
    --enable-__cxa_atexit       \
    --enable-languages=c,c++    \
    --disable-libstdcxx-pch     \
    --disable-multilib          \
    --disable-bootstrap         \
    --disable-libgomp           \
    --with-mpfr-include=$SRC_DIR/mpfr/src \
    --with-mpfr-lib=$(pwd)/mpfr/src/.libs >> $CRTLOG
    
    
finishDir
ln -sv gcc /tools/bin/cc
# ===============================================================




# ===============================================================
# CHECKPOINT

cd $LFS/sources

echo	"


At this point, it is imperative to stop and ensure that the 
basic functions (compiling and linking) of the new 
toolchain are working as expected.

"
echo 'main(){}' > dummy.c
cc dummy.c
readelf -l a.out | grep ': /tools'

echo	"
If everything is working correctly, there should be no errors, 
and the output of the last command will be of the form:
[Requesting program interpreter: /tools/lib/ld-linux.so.2]
Note that /tools/lib, or /tools/lib64 for 64-bit machines appears 
as the prefix of the dynamic linker.

If the output is not shown as above or there was no output at all, 
then something is wrong. Investigate and retrace the steps to
find out where the problem is and correct it. This issue must 
be resolved before continuing on.

Press CTRL+C to stop.
Press RETURN to continue.
"

# Once all is well, clean up the test files:
rm -v dummy.c a.out

read dummy

# CHECKPOINT
# ===============================================================



fi


# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#            STEP   3
# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
if $PERFORM_STEP_3; then

# ===============================================================
initDirEx "5.10." "tcl8.5.12-src" "gz" "tcl8.5.12"
	cd unix
	./configure --prefix=/tools >> $CRTLOG
	make >> $CRTLOG
	make install >> $CRTLOG

	# Make the installed library writable so debugging symbols can be removed later:
	chmod -v u+w /tools/lib/libtcl8.5.so

	# Install Tcl's headers. The next package, Expect, requires them to build.
	make install-private-headers >> $CRTLOG

	# Now make a necessary symbolic link:
	ln -sv tclsh8.5 /tools/bin/tclsh
rDir
initDir "5.11." "expect5.45" "gz"
	# First, force Expect's configure script to use /bin/stty instead 
	# of a /usr/local/bin/stty it may find on the host system. 
	# This will ensure that our test suite tools remain sane 
	# for the final builds of our toolchain: 
	cp -v configure{,.orig}
	sed 's:/usr/local/bin:/bin:' configure.orig > configure

	./configure --prefix=/tools --with-tcl=/tools/lib \
	  --with-tclinclude=/tools/include > $CRTLOG
	  
	make >> $CRTLOG
	# SCRIPTS="" This prevents installation of the 
	# supplementary Expect scripts, which are not needed.
	make SCRIPTS="" install >> $CRTLOG
rDir
doItAll "5.12." "dejagnu-1.5" "gz"
doItAll "5.13." "check-0.9.8" "gz"
initDir "5.14." "ncurses-5.9" "gz"
	./configure --prefix=/tools --with-shared \
		--without-debug --without-ada --enable-overwrite >> $CRTLOG
finishDir
initDir "5.15." "bash-4.2" "gz"
	patch -Np1 -i ../bash-4.2-fixes-9.patch >> $CRTLOG
	./configure --prefix=/tools --without-bash-malloc >> $CRTLOG
finishDir
ln -sv bash /tools/bin/sh
initDir "5.16." "bzip2-1.0.6" "gz"
	make >> $CRTLOG
	make PREFIX=/tools install >> $CRTLOG
rDir
initDir "5.17." "coreutils-8.19" "xz"
	./configure --prefix=/tools \
		--enable-install-program=hostname  >> $CRTLOG
finishDir
initDir "5.18." "diffutils-3.2" "gz"
	# Fix an incompatibility between this package and Glibc-2.16.0: 
	sed -i -e '/gets is a/d' lib/stdio.in.h
	./configure --prefix=/tools  >> $CRTLOG
finishDir
doItAll "5.19." "findutils-4.4.2" "gz"
doItAll "5.20." "gawk-4.0.1" "xz"
initDir "5.22." "gettext-0.18.1.1" "gz"
	# Fix an incompatibility between this package and Glibc-2.16.0:
	sed -i -e '/gets is a/d' gettext-*/*/stdio.in.h

	cd gettext-tools
	EMACS="no" ./configure --prefix=/tools --disable-shared  >> $CRTLOG
	make -C gnulib-lib  >> $CRTLOG
	make -C src msgfmt  >> $CRTLOG
	cp -v src/msgfmt /tools/bin
rDir
doItAll "5.23." "grep-2.14" "xz"
doItAll "5.24." "gzip-1.5" "xz"
initDir "5.25." "m4-1.4.16" "bz2"
	sed -i -e '/gets is a/d' lib/stdio.in.h
	./configure --prefix=/tools  >> $CRTLOG
finishDir
doItAll "5.26." "make-3.82" "bz2"
doItAll "5.27." "patch-2.7.1" "xz"
initDir "5.28." "perl-5.16.1" "bz2"
	patch -Np1 -i ../perl-5.16.1-libc-2.patch >> $CRTLOG
	sh Configure -des -Dprefix=/tools >> $CRTLOG
	make >> $CRTLOG
	cp -v perl cpan/podlators/pod2man /tools/bin
	mkdir -pv /tools/lib/perl5/5.16.1
	cp -Rv lib/* /tools/lib/perl5/5.16.1
rDir
doItAll "5.29." "sed-4.2.1" "bz2"

initDir "5.30." "tar-1.26" "bz2"
	sed -i -e '/gets is a/d' gnu/stdio.in.h
	./configure --prefix=/tools >> $CRTLOG
finishDir
initDirEx "5.31." "texinfo-4.13a" "gz" "texinfo-4.13"
	./configure --prefix=/tools >> $CRTLOG
finishDir
doItAll "5.32." "xz-5.0.4" "xz"
# ===============================================================


fi


# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#            STEP   4
# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
if $PERFORM_STEP_4; then

echo	"
The executables and libraries built so far contain
about 70 MB of unneeded debugging symbols.
Removing those symbols...
"
#strip --strip-debug /tools/lib/*
#strip --strip-unneeded /tools/{,s}bin/*

echo	"
Removing documentation...
"
rm -rf /tools/{,share}/{info,man,doc}

fi













